import ima from '../ima.js'
import doubao from '../doubao.js'
import fs from 'fs/promises'
import path from 'path'
import { jsonDir, projectConfig, saveProjectConfig } from '../../config.js'
import { extractJson, sleep, } from '../../util/util.js'
import { glob } from 'glob'
import { jsonrepair } from 'jsonrepair'

class CsEvalQuestion {
  constructor() { }

  initRoute(koa) {
    // this.log('开始任务', 'http://127.0.0.1:3001/cs-eval-question')
    this.log('开始任务', 'http://127.0.0.1:3001/cs-eval-question/jgyz')
    koa.router.get('/cs-eval-question', ctx => {
      setTimeout(() => {
        this.csEvalQuestions()
      }, 0)

      ctx.body = {
        code: 0,
        msg: 'success',
      }
    })

    koa.router.get('/cs-eval-question/jgyz', ctx => {
      setTimeout(() => {
        this.jgyz()
      }, 0)

      ctx.body = {
        code: 0,
        msg: 'success',
      }
    })
  }

  log(...args) {
    console.log('[cs-eval-questions]', ...args)
  }

  extractAnswerWithRegexRobust(str) {
    // 匹配 "answer": 后面可能有空格，然后是引号内的内容
    // 支持单引号和双引号，考虑可能的转义字符
    const regex = /"answer"\s*:\s*["']([^"']*)["']/;
    const match = str.match(regex);
    return match ? match[1] : null;
  }

  // 格式化答案
  formatAnswer(answer) {
    // 统一答案格式
    if (Array.isArray(answer)) {
      answer = json.answer.join('')
    } else if (answer.includes("、")) {
      let tmp = answer.split("、");
      answer = tmp.join("");
    }

    else if (answer.includes(".")) {
      let tmp = answer.split(".");
      answer = tmp.join("");
    }

    else if (answer.includes("，")) {
      let tmp = answer.split("，");
      answer = tmp.join("");
    }

    else if (answer.includes(" ")) {
      let tmp = answer.split(" ");
      answer = tmp.join("");
    }

    return answer
  }

  // 这里面有的所有题目都有答案，和之前一样让大模型输出，然后存储输出的json内容，但最后需要校验输出的答案是否与给定的答案一致，如果不一致就要重新生成，直到与答案一致
  async jgyz() {
    const config = projectConfig['jgyz']

    const dir = path.join(import.meta.dirname, '../../data/结果验证')
    const singalSrc = path.join(dir, './singal/**/*.txt').replace(/\\/g, '/')
    let files = await glob(singalSrc)

    // 按数字顺序排序
    files = files.sort((a, b) => {
      return a.localeCompare(b, undefined, { numeric: true });
    });


    if (config.end == 0) config.end = files.length

    for (let i = config.start; i <= config.end; i++) {
      // start必须从1开始算
      const filename = files[i - 1]
      const { name } = path.parse(filename)
      const prompt = await fs.readFile(filename, 'utf-8')

      const fileId = name.split('-')[0]
      const answer = name.split('-')[1]

      console.log('filename', filename);
      console.log('fileId', fileId);
      console.log('正确答案', answer);

      let count = 0;


      while (true) {
        let aiAnswer;
        let json;
        let result
        try {
          result = await doubao.message(prompt).then(res => {
            return res.contentText
          })
          console.log('result', result);

          // let json = extractJson(result)
          const repaired = jsonrepair(result.replace(/^json/, ''))
          console.log('repaired', repaired, typeof repaired);
          json = JSON.parse(repaired)
          aiAnswer = this.formatAnswer(json.answer)
        } catch (e) {
          console.error(e)
        }

        if (result && !aiAnswer) {
          try {
            console.log('json获取答案失败，从字符串中获取');
            aiAnswer = this.formatAnswer(this.extractAnswerWithRegexRobust(result))
          } catch (e) {
            console.error(e)
          }
        }

        if (answer == aiAnswer) {
          console.log('结果一致');

          if (json) {
            await fs.writeFile(path.join(dir, `json/${fileId}.json`), JSON.stringify(json))
          } else {
            await fs.writeFile(path.join(dir, `json/${fileId}-error.txt`), result)
          }

          break;
        } else {
          console.log('结果不一致');
          count++
        }


        if (count > 5) {
          console.log('超过5次了');
          await fs.writeFile(path.join(dir, `json/${fileId}-fail.txt`), '')
          break;
        }
      }

      config.start = i + 1
      saveProjectConfig()

      const delay = config.sleep
      this.log('等待', delay + '秒')
      await sleep(delay * 1000)
    }
  }

  async csEvalQuestions() {

    const config = projectConfig['cs-eval-question']

    // const file = await fs.readFile(path.join(import.meta.dirname, './cs-eval-questions.jsonl'), 'utf-8')
    // const json = JSON.parse(file)
    // let prompt = await fs.readFile(path.join(import.meta.dirname, './prompt.txt'), 'utf-8')

    const singalSrc = path.join(import.meta.dirname, '../../data/singal/**/*.txt').replace(/\\/g, '/')
    let files = await glob(singalSrc)

    // 按数字顺序排序
    files = files.sort((a, b) => {

      return a.localeCompare(b, undefined, { numeric: true });
    });


    if (config.end == 0) config.end = files.length

    for (let i = config.start; i <= config.end; i++) {
      // start必须从1开始算
      const filename = files[i - 1]
      const fileId = filename.split('\\').pop().split('.')[0]
      const prompt = await fs.readFile(filename, 'utf-8')

      console.log('filename', filename);

      const data = []

      for (let time = 0; time <= 2; time++) {
        this.log('任务进度', `${config.start}/${config.end}`, config.end / config.end / 100 + '%')

        let res
        try {
          res = await this.message(prompt)

          const json = extractJson(res)

          if (!json.think || json.think == '') {
            throw '没有json'
          }

          if (json.answer.indexOf('失败') != -1) throw '分析失败'

          let answer = json.answer

          // 统一答案格式
          if (Array.isArray(answer)) {
            answer = json.answer.join('')
          } else if (answer.includes("、")) {
            let tmp = answer.split("、");
            answer = tmp.join("");
          }

          else if (answer.includes(".")) {
            let tmp = answer.split(".");
            answer = tmp.join("");
          }

          else if (answer.includes("，")) {
            let tmp = answer.split("，");
            answer = tmp.join("");
          }

          else if (answer.includes(" ")) {
            let tmp = answer.split(" ");
            answer = tmp.join("");
          }

          console.log('answer', answer);

          json.answer = answer

          await fs.writeFile(path.join(jsonDir, `${fileId}-${time + 1}.json`), JSON.stringify(json))

          data.push(json)

        } catch (e) {
          // config.errors.push({
          //   index: i,
          //   error: e.message,
          // })

          this.log('处理失败', e)
          this.log('error', path.join(jsonDir, `${fileId}-${time + 1}-error.txt`))

          await fs.writeFile(path.join(jsonDir, `${fileId}-${time + 1}-error.txt`), res)
        }

        config.start = i + 1
        saveProjectConfig()

        // const delay = random(config.sleep, config.sleep * 3)
        const delay = config.sleep
        this.log('等待', delay + '秒')
        await sleep(delay * 1000)

      }

      try {
        let isSuccess = true
        let answer
        data.map((item,) => {
          console.log('item.answer', item.answer);
          if (answer == undefined) answer = item.answer
          if (item.answer != answer) isSuccess = false
        })


        if (isSuccess && data.length == 3) {
          let maxlength = 0
          let maxIndex = 0
          data.map((item, index) => {
            const str = JSON.stringify(item)
            if (str.length > maxlength) {
              maxlength = str.length
              maxIndex = index
            }
          })

          console.log('匹配成功', maxlength, maxIndex);

          await fs.writeFile(path.join(jsonDir, 'success', `${fileId}-${maxIndex + 1}.json`), JSON.stringify(data[maxIndex]))
        } else {
          console.log('匹配失败');
          await fs.writeFile(path.join(jsonDir, 'fail', `${fileId}.txt`), "匹配失败")
        }
      } catch (e) {
        console.error(e);
      }


    }
  }

  // async csEvalQuestions() {
  //   const file = await fs.readFile(path.join(import.meta.dirname, './cs-eval-questions.jsonl'), 'utf-8')
  //   const json = JSON.parse(file)
  //   const config = projectConfig['cs-eval-question']

  //   let prompt = await fs.readFile(path.join(import.meta.dirname, './prompt.txt'), 'utf-8')
  //   if (config.end == 0) config.end = json.length

  //   for (let i = config.start; i < config.end; i++) {
  //     const item = json[i]

  //     this.log('任务进度', `${config.start}/${config.end}`, config.end / config.end / 100 + '%')

  //     let res
  //     try {
  //       res = await this.message(prompt + item.prompt)

  //       const json = extractJson(res)

  //       if (!json.think || json.think == '') {
  //         throw '没有json'
  //       }

  //       if (json.answer.indexOf('失败') != -1) throw '分析失败'

  //       await fs.writeFile(path.join(jsonDir, `${item.id}.json`), JSON.stringify(json))

  //     } catch (e) {
  //       // config.errors.push({
  //       //   index: i,
  //       //   error: e.message,
  //       // })

  //       this.log('处理失败', e)
  //       this.log('error', path.join(jsonDir, `${item.id}-error.txt`))

  //       await fs.writeFile(path.join(jsonDir, `${item.id}-error.txt`), res)
  //     }

  //     config.start = i + 1
  //     saveProjectConfig()

  //     // const delay = random(config.sleep, config.sleep * 3)
  //     const delay = config.sleep
  //     this.log('等待', delay + '秒')
  //     await sleep(delay * 1000)
  //   }
  // }

  // 发送消息，带重试
  async message(msg, retry = 0) {
    const config = projectConfig['cs-eval-question']

    // if (retry >= config.retryMax) throw new Error(`重试${retry}次，还是获取失败，跳过当前内容`)
    // if (retry > 0) {
    //   doubao.page = null
    //   await playwrightApi.close()

    //   this.log(`重试${retry}次，等待${config.retrySleep}秒`)

    //   await sleep(config.retrySleep * 1000)
    //   await playwrightApi.launch()
    // }

    // const res = await doubao.message(msg)
    // if (res.thinkText) return res
    return await ima.message(msg)

    // return await this.message(msg, retry + 1)
  }
}

export default new CsEvalQuestion()
